// 1. boolean
const x: boolean = false
const y: boolean = true

// 2. string

// 3. number

// 4. bigint  bigint 与 number并不兼容
const var01: bigint = 123n

// 5. symbol
const var02: symbol = Symbol()

// 6. object
const var03: object = { foo: 123 }
const var04: object = [1, 2, 3]
const var05: object = (x: number) => x + 1

// 7. undefined
const var06: undefined = undefined

// 8. null
const var07: null = null

const s1: String = '123'
const s2: String = new String('123')

const s3: string = '123'
// const s4: string = new String('123')  报错
// 大写类型同时包含包装对象和字面量两种情况，小写类型只包含字面量，不包含包装对象。
// number => Number   Number !=> number
// 建议直接使用小写类型 且官方大多数都直接使用小写类型

// 空对象 {} 是 Object类型的简写形式
let obj: {}

obj = 1
obj = '1'
obj = false
obj = { name: 'www', age: 66 }

// 小写的object类型代表 JavaScript 里面的狭义对象，即可以用字面量表示的对象，只包含对象、数组和函数，不包括原始类型的值。
let obj1: object

obj1 = { foo: 123 }
obj1 = [1, 2]
obj1 = (a: number) => a + 1
// obj1 = true; // 报错
// obj1 = 'hi'; // 报错
// obj1 = 1; // 报错

// undefined和null既是值，又是类型。
let age: number = 24

// age = null;      // 正确
// age = undefined; // 正确

const x1 = { foo: 1 }
console.log(x1.foo)

// const x2: 5 = 4 + 1     number !=> 5 number无法赋值给字面量类型
const x4: 5 = (4 + 1) as 5 // 强行断言
const x2: number = 5
const x3: number = 4 + 1

let x5: number | string
x5 = 1
x5 = '1'

// 联合类型定义时时 类型方法  使用时需要类型缩小
// type widening    type narrowing

// 交叉类型 => 既要又要
let x6: number & string // never类型
let obj2: { foo: number } & { bar: string }
obj2 = { foo: 1, bar: '2' }

// 类型别名
type Color = 'red' | 'green' | 'blue'
let thing: Color = 'blue'

// typeof
typeof undefined; // "undefined"
typeof true; // "boolean"
typeof 1337; // "number"
typeof "foo"; // "string"
typeof {}; // "object"
typeof parseInt; // "function"
typeof Symbol(); // "symbol"
typeof 127n // "bigint"

// 类型移植
const a = { x : 0 }
type myType = typeof a
type myType01 = typeof a.x

// TypeScript 规定，typeof 的参数只能是标识符，不能是需要运算的表达式。
type T = typeof Date
type myType02 =  typeof Array

// TypeScript 的一个规则是，凡是可以使用父类型的地方，都可以使用子类型，但是反过来不行。
let a1: number = 1
let b: number | string = a1

let a2: 'h1' = 'h1'
let b2: string = 'hello'
b2 = a2
// a2 = b2
// hi是string的子类型，string是hi的父类型。所以，变量a可以赋值给变量b，但是反过来就会报错。
// 多的可以给少的 但是少的无法给多的
